#pragma once

#include <vex/core/contract/handle.h>

namespace vex { namespace functional { namespace contract {
    template<class TSignature> struct delegate;

    template<class TRet>
    struct VEX_ABSTRACT delegate<TRet ()> 
        : virtual public core::contract::handle 
    {
        typedef TRet result_type;
        virtual TRet invoke() const = 0;
        VEX_PROTECT_CONTRACT(delegate);
    };

    template<class TRet, class TArg1>
    struct VEX_ABSTRACT delegate<TRet (TArg1)> 
        : virtual public core::contract::handle 
    {
        typedef TRet result_type;
        virtual TRet invoke(TArg1) const = 0;
        VEX_PROTECT_CONTRACT(delegate);
    };

    template<class TRet, class TArg1, class TArg2>
    struct VEX_ABSTRACT delegate<TRet (TArg1, TArg2)> 
        : virtual public core::contract::handle 
    {
        typedef TRet result_type;
        virtual TRet invoke(TArg1, TArg2) const = 0;
        VEX_PROTECT_CONTRACT(delegate);
    };

    template<class TRet, class TArg1, class TArg2, class TArg3>
    struct VEX_ABSTRACT delegate<TRet (TArg1, TArg2, TArg3)> 
        : virtual public core::contract::handle 
    {
        typedef TRet result_type;
        virtual TRet invoke(TArg1, TArg2, TArg3) const = 0;
        VEX_PROTECT_CONTRACT(delegate);
    };

    template<class TRet, class TArg1, class TArg2, class TArg3, class TArg4>
    struct VEX_ABSTRACT delegate<TRet (TArg1, TArg2, TArg3, TArg4)> 
        : public virtual core::contract::handle 
    {
        typedef TRet result_type;
        virtual TRet invoke(TArg1, TArg2, TArg3, TArg4) const = 0;
        VEX_PROTECT_CONTRACT(delegate);
    };

    template<class TRet, class TArg1, class TArg2, class TArg3, class TArg4, class TArg5>
    struct VEX_ABSTRACT delegate<TRet (TArg1, TArg2, TArg3, TArg4, TArg5)> 
        : virtual public core::contract::handle 
    {
        typedef TRet result_type;
        virtual TRet invoke(TArg1, TArg2, TArg3, TArg4, TArg5) const = 0;
        VEX_PROTECT_CONTRACT(delegate);
    };
}}}